home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / cpu / i8039 / i8039.c < prev    next >
C/C++ Source or Header  |  2000-05-18  |  48KB  |  1,087 lines

  1. /**************************************************************************
  2.  *                      Intel 8039 Portable Emulator                      *
  3.  *                                                                        *
  4.  *                     Copyright (C) 1997 by Mirko Buffoni                  *
  5.  *    Based on the original work (C) 1997 by Dan Boris, an 8048 emulator      *
  6.  *     You are not allowed to distribute this software commercially       *
  7.  *        Please, notify me, if you make any changes to this file         *
  8.  **************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include "cpuintrf.h"
  14. #include "mamedbg.h"
  15. #include "i8039.h"
  16.  
  17.  
  18. /* Layout of the registers in the debugger */
  19. static UINT8 i8039_reg_layout[] = {
  20.     I8039_PC, I8039_SP, I8039_PSW, I8039_A, I8039_IRQ_STATE, -1,
  21.     I8039_R0, I8039_R1, I8039_R2, I8039_R3, I8039_R4, I8039_R5, I8039_R6, I8039_R7, 0
  22. };
  23.  
  24. /* Layout of the debugger windows x,y,w,h */
  25. static UINT8 i8039_win_layout[] = {
  26.      0, 0,80, 2,    /* register window (top rows) */
  27.      0, 3,24,19,    /* disassembler window (left colums) */
  28.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  29.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  30.      0,23,80, 1,    /* command line window (bottom rows) */
  31. };
  32.  
  33. #define M_RDMEM(A)      I8039_RDMEM(A)
  34. #define M_RDOP(A)       I8039_RDOP(A)
  35. #define M_RDOP_ARG(A)   I8039_RDOP_ARG(A)
  36. #define M_IN(A)        I8039_In(A)
  37. #define M_OUT(A,V)    I8039_Out(A,V)
  38.  
  39. #if OLDPORTHANDLING
  40.         #define port_r(A)    I8039_port_r(A)
  41.         #define port_w(A,V)    I8039_port_w(A,V)
  42.         #define test_r(A)    I8039_test_r(A)
  43.         #define test_w(A,V)    I8039_test_w(A,V)
  44.         #define bus_r        I8039_bus_r
  45.         #define bus_w(V)    I8039_bus_w(V)
  46. #else
  47.         #define port_r(A)    I8039_In(I8039_p0 + A)
  48.         #define port_w(A,V)    I8039_Out(I8039_p0 + A,V)
  49.         #define test_r(A)    I8039_In(I8039_t0 + A)
  50.         #define test_w(A,V)    I8039_Out(I8039_t0 + A,V)
  51.         #define bus_r()        I8039_In(I8039_bus)
  52.         #define bus_w(V)    I8039_Out(I8039_bus,V)
  53. #endif
  54.  
  55. #define C_FLAG          0x80
  56. #define A_FLAG          0x40
  57. #define F_FLAG          0x20
  58. #define B_FLAG          0x10
  59.  
  60. typedef struct
  61. {
  62.     PAIR    PREPC;            /* previous program counter */
  63.     PAIR    PC;             /* program counter */
  64.     UINT8   A, SP, PSW;
  65.     UINT8   RAM[128];
  66.     UINT8   bus, f1;        /* Bus data, and flag1 */
  67.  
  68.     int     pending_irq,irq_executing, masterClock, regPtr;
  69.     UINT8   t_flag, timer, timerON, countON, xirq_en, tirq_en;
  70.     UINT16  A11, A11ff;
  71.     int     irq_state;
  72.     int     (*irq_callback)(int irqline);
  73. } I8039_Regs;
  74.  
  75. static I8039_Regs R;
  76. int    i8039_ICount;
  77. static UINT8 Old_T1;
  78.  
  79. /* The opcode table now is a combination of cycle counts and function pointers */
  80. typedef struct {
  81.     unsigned cycles;
  82.     void (*function) (void);
  83. }    s_opcode;
  84.  
  85. #define POSITIVE_EDGE_T1  (((T1-Old_T1) > 0) ? 1 : 0)
  86. #define NEGATIVE_EDGE_T1  (((Old_T1-T1) > 0) ? 1 : 0)
  87.  
  88. #define M_Cy    ((R.PSW & C_FLAG) >> 7)
  89. #define M_Cn    (!M_Cy)
  90. #define M_Ay    ((R.PSW & A_FLAG))
  91. #define M_An    (!M_Ay)
  92. #define M_F0y   ((R.PSW & F_FLAG))
  93. #define M_F0n   (!M_F0y)
  94. #define M_By    ((R.PSW & B_FLAG))
  95. #define M_Bn    (!M_By)
  96.  
  97. #define intRAM    R.RAM
  98. #define regPTR    R.regPtr
  99.  
  100. #define R0    intRAM[regPTR  ]
  101. #define R1    intRAM[regPTR+1]
  102. #define R2    intRAM[regPTR+2]
  103. #define R3    intRAM[regPTR+3]
  104. #define R4    intRAM[regPTR+4]
  105. #define R5    intRAM[regPTR+5]
  106. #define R6    intRAM[regPTR+6]
  107. #define R7    intRAM[regPTR+7]
  108.  
  109.  
  110. INLINE void CLR (UINT8 flag) { R.PSW &= ~flag; }
  111. INLINE void SET (UINT8 flag) { R.PSW |= flag;  }
  112.  
  113.  
  114. /* Get next opcode argument and increment program counter */
  115. INLINE unsigned M_RDMEM_OPCODE (void)
  116. {
  117.         unsigned retval;
  118.         retval=M_RDOP_ARG(R.PC.w.l);
  119.         R.PC.w.l++;
  120.         return retval;
  121. }
  122.  
  123. INLINE void push(UINT8 d)
  124. {
  125.     intRAM[8+R.SP++] = d;
  126.     R.SP  = R.SP & 0x0f;
  127.     R.PSW = R.PSW & 0xf8;
  128.     R.PSW = R.PSW | (R.SP >> 1);
  129. }
  130.  
  131. INLINE UINT8 pull(void) {
  132.     R.SP  = (R.SP + 15) & 0x0f;        /*  if (--R.SP < 0) R.SP = 15;  */
  133.     R.PSW = R.PSW & 0xf8;
  134.     R.PSW = R.PSW | (R.SP >> 1);
  135.     /* regPTR = ((M_By) ? 24 : 0);  regPTR should not change */
  136.     return intRAM[8+R.SP];
  137. }
  138.  
  139. INLINE void daa_a(void)
  140. {
  141.     if ((R.A & 0x0f) > 0x09 || (R.PSW & A_FLAG))
  142.         R.A += 0x06;
  143.     if ((R.A & 0xf0) > 0x90 || (R.PSW & C_FLAG))
  144.     {
  145.         R.A += 0x60;
  146.         SET(C_FLAG);
  147.     } else CLR(C_FLAG);
  148. }
  149.  
  150. INLINE void M_ADD(UINT8 dat)
  151. {
  152.     UINT16 temp;
  153.  
  154.     CLR(C_FLAG | A_FLAG);
  155.     if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG);
  156.     temp = R.A + dat;
  157.     if (temp > 0xff) SET(C_FLAG);
  158.     R.A  = temp & 0xff;
  159. }
  160.  
  161. INLINE void M_ADDC(UINT8 dat)
  162. {
  163.     UINT16 temp;
  164.  
  165.     CLR(A_FLAG);
  166.     if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG);
  167.     temp = R.A + dat + M_Cy;
  168.     CLR(C_FLAG);
  169.     if (temp > 0xff) SET(C_FLAG);
  170.     R.A  = temp & 0xff;
  171. }
  172.  
  173. INLINE void M_CALL(UINT16 addr)
  174. {
  175.     push(R.PC.b.l);
  176.     push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
  177.     R.PC.w.l = addr;
  178.     #ifdef MESS
  179.         change_pc(addr);
  180.     #endif
  181.  
  182. }
  183.  
  184. INLINE void M_XCHD(UINT8 addr)
  185. {
  186.     UINT8 dat = R.A & 0x0f;
  187.     R.A &= 0xf0;
  188.     R.A |= intRAM[addr] & 0x0f;
  189.     intRAM[addr] &= 0xf0;
  190.     intRAM[addr] |= dat;
  191. }
  192.  
  193.  
  194. INLINE void M_ILLEGAL(void)
  195. {
  196.     logerror("I8039:  PC = %04x,  Illegal opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
  197. }
  198.  
  199. INLINE void M_UNDEFINED(void)
  200. {
  201.     logerror("I8039:  PC = %04x,  Unimplemented opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
  202. }
  203.  
  204.  
  205. #if OLDPORTHANDLING
  206.     UINT8 I8039_port_r(UINT8 port)              { return R.p[port & 7]; }
  207.     void I8039_port_w(UINT8 port, UINT8 data) { R.p[port & 7] = data; }
  208.  
  209.     UINT8 I8039_test_r(UINT8 port)              { return R.t[port & 1]; }
  210.     void I8039_test_w(UINT8 port, UINT8 data) { R.t[port & 1] = data; }
  211.  
  212.     UINT8 I8039_bus_r(void)      { return R.bus; }
  213.     void I8039_bus_w(UINT8 data) { R.bus = data; }
  214. #endif
  215.  
  216. static void illegal(void)    { M_ILLEGAL(); }
  217.  
  218. static void add_a_n(void)    { M_ADD(M_RDMEM_OPCODE()); }
  219. static void add_a_r0(void)   { M_ADD(R0); }
  220. static void add_a_r1(void)   { M_ADD(R1); }
  221. static void add_a_r2(void)   { M_ADD(R2); }
  222. static void add_a_r3(void)   { M_ADD(R3); }
  223. static void add_a_r4(void)   { M_ADD(R4); }
  224. static void add_a_r5(void)   { M_ADD(R5); }
  225. static void add_a_r6(void)   { M_ADD(R6); }
  226. static void add_a_r7(void)   { M_ADD(R7); }
  227. static void add_a_xr0(void)  { M_ADD(intRAM[R0 & 0x7f]); }
  228. static void add_a_xr1(void)  { M_ADD(intRAM[R1 & 0x7f]); }
  229. static void adc_a_n(void)    { M_ADDC(M_RDMEM_OPCODE()); }
  230. static void adc_a_r0(void)   { M_ADDC(R0); }
  231. static void adc_a_r1(void)   { M_ADDC(R1); }
  232. static void adc_a_r2(void)   { M_ADDC(R2); }
  233. static void adc_a_r3(void)   { M_ADDC(R3); }
  234. static void adc_a_r4(void)   { M_ADDC(R4); }
  235. static void adc_a_r5(void)   { M_ADDC(R5); }
  236. static void adc_a_r6(void)   { M_ADDC(R6); }
  237. static void adc_a_r7(void)   { M_ADDC(R7); }
  238. static void adc_a_xr0(void)  { M_ADDC(intRAM[R0 & 0x7f]); }
  239. static void adc_a_xr1(void)  { M_ADDC(intRAM[R1 & 0x7f]); }
  240. static void anl_a_n(void)    { R.A &= M_RDMEM_OPCODE(); }
  241. static void anl_a_r0(void)   { R.A &= R0; }
  242. static void anl_a_r1(void)   { R.A &= R1; }
  243. static void anl_a_r2(void)   { R.A &= R2; }
  244. static void anl_a_r3(void)   { R.A &= R3; }
  245. static void anl_a_r4(void)   { R.A &= R4; }
  246. static void anl_a_r5(void)   { R.A &= R5; }
  247. static void anl_a_r6(void)   { R.A &= R6; }
  248. static void anl_a_r7(void)   { R.A &= R7; }
  249. static void anl_a_xr0(void)  { R.A &= intRAM[R0 & 0x7f]; }
  250. static void anl_a_xr1(void)  { R.A &= intRAM[R1 & 0x7f]; }
  251. static void anl_bus_n(void)  { bus_w( bus_r() & M_RDMEM_OPCODE() ); }
  252. static void anl_p1_n(void)   { port_w( 1, port_r(1) & M_RDMEM_OPCODE() ); }
  253. static void anl_p2_n(void)   { port_w( 2, port_r(2) & M_RDMEM_OPCODE() ); }
  254. static void anld_p4_a(void)  { port_w( 4, port_r(4) & M_RDMEM_OPCODE() ); }
  255. static void anld_p5_a(void)  { port_w( 5, port_r(5) & M_RDMEM_OPCODE() ); }
  256. static void anld_p6_a(void)  { port_w( 6, port_r(6) & M_RDMEM_OPCODE() ); }
  257. static void anld_p7_a(void)  { port_w( 7, port_r(7) & M_RDMEM_OPCODE() ); }
  258. static void call(void)         { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | R.A11); }
  259. static void call_1(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x100 | R.A11); }
  260. static void call_2(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x200 | R.A11); }
  261. static void call_3(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x300 | R.A11); }
  262. static void call_4(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x400 | R.A11); }
  263. static void call_5(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x500 | R.A11); }
  264. static void call_6(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x600 | R.A11); }
  265. static void call_7(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x700 | R.A11); }
  266. static void clr_a(void)      { R.A=0; }
  267. static void clr_c(void)      { CLR(C_FLAG); }
  268. static void clr_f0(void)     { CLR(F_FLAG); }
  269. static void clr_f1(void)     { R.f1 = 0; }
  270. static void cpl_a(void)      { R.A ^= 0xff; }
  271. static void cpl_c(void)      { R.PSW ^= C_FLAG; }
  272. static void cpl_f0(void)     { R.PSW ^= F_FLAG; }
  273. static void cpl_f1(void)     { R.f1 ^= 1; }
  274. static void dec_a(void)      { R.A--; }
  275. static void dec_r0(void)     { R0--; }
  276. static void dec_r1(void)     { R1--; }
  277. static void dec_r2(void)     { R2--; }
  278. static void dec_r3(void)     { R3--; }
  279. static void dec_r4(void)     { R4--; }
  280. static void dec_r5(void)     { R5--; }
  281. static void dec_r6(void)     { R6--; }
  282. static void dec_r7(void)     { R7--; }
  283. static void dis_i(void)      { R.xirq_en = 0; }
  284. static void dis_tcnti(void)  { R.tirq_en = 0; }
  285. #ifdef MESS
  286.     static void djnz_r0(void)     { UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); }}
  287.     static void djnz_r1(void)     { UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  288.     static void djnz_r2(void)     { UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  289.     static void djnz_r3(void)     { UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  290.     static void djnz_r4(void)     { UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  291.     static void djnz_r5(void)     { UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  292.     static void djnz_r6(void)     { UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  293.     static void djnz_r7(void)     { UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  294. #else
  295.     static void djnz_r0(void)     { UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  }}
  296.     static void djnz_r1(void)     { UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  297.     static void djnz_r2(void)     { UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  298.     static void djnz_r3(void)     { UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  299.     static void djnz_r4(void)     { UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  300.     static void djnz_r5(void)     { UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  301.     static void djnz_r6(void)     { UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  302.     static void djnz_r7(void)     { UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  303. #endif
  304. static void en_i(void)       { R.xirq_en = 1; if (R.irq_state != CLEAR_LINE) R.pending_irq |= I8039_EXT_INT; }
  305. static void en_tcnti(void)   { R.tirq_en = 1; }
  306. static void ento_clk(void)   { M_UNDEFINED(); }
  307. static void in_a_p1(void)    { R.A = port_r(1); }
  308. static void in_a_p2(void)    { R.A = port_r(2); }
  309. static void ins_a_bus(void)  { R.A = bus_r(); }
  310. static void inc_a(void)      { R.A++; }
  311. static void inc_r0(void)     { R0++; }
  312. static void inc_r1(void)     { R1++; }
  313. static void inc_r2(void)     { R2++; }
  314. static void inc_r3(void)     { R3++; }
  315. static void inc_r4(void)     { R4++; }
  316. static void inc_r5(void)     { R5++; }
  317. static void inc_r6(void)     { R6++; }
  318. static void inc_r7(void)     { R7++; }
  319. static void inc_xr0(void)    { intRAM[R0 & 0x7f]++; }
  320. static void inc_xr1(void)    { intRAM[R1 & 0x7f]++; }
  321.  
  322. /* static void jmp(void)        { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | R.A11; }
  323.  */
  324.  
  325. static void jmp(void)
  326. {
  327.   UINT8 i=M_RDOP(R.PC.w.l);
  328.   UINT16 oldpc,newpc;
  329.  
  330.   oldpc = R.PC.w.l-1;
  331.   R.PC.w.l = i | R.A11;
  332.   #ifdef MESS
  333.       change_pc(R.PC.w.l);
  334.   #endif
  335.   newpc = R.PC.w.l;
  336.   if (newpc == oldpc) { if (i8039_ICount > 0) i8039_ICount = 0; } /* speed up busy loop */
  337.   else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00)    /* NOP - Gyruss */
  338.       { if (i8039_ICount > 0) i8039_ICount = 0; }
  339. }
  340.  
  341. #ifdef MESS
  342.     static void jmp_1(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x100 | R.A11; change_pc(R.PC.w.l); }
  343.     static void jmp_2(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x200 | R.A11; change_pc(R.PC.w.l); }
  344.     static void jmp_3(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x300 | R.A11; change_pc(R.PC.w.l); }
  345.     static void jmp_4(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x400 | R.A11; change_pc(R.PC.w.l); }
  346.     static void jmp_5(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x500 | R.A11; change_pc(R.PC.w.l); }
  347.     static void jmp_6(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x600 | R.A11; change_pc(R.PC.w.l); }
  348.     static void jmp_7(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x700 | R.A11; change_pc(R.PC.w.l); }
  349.     static void jmpp_xa(void)     { UINT16 addr = (R.PC.w.l & 0xf00) | R.A; R.PC.w.l = (R.PC.w.l & 0xf00) | M_RDMEM(addr); change_pc(R.PC.w.l); }
  350.     static void jb_0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  351.     static void jb_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  352.     static void jb_2(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  353.     static void jb_3(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  354.     static void jb_4(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  355.     static void jb_5(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  356.     static void jb_6(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  357.     static void jb_7(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  358.     static void jf0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  359.     static void jf_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  360.     static void jnc(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  361.     static void jc(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  362.     static void jni(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state != CLEAR_LINE) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  363.     static void jnt_0(void)      { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  364.     static void jt_0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  365.     static void jnt_1(void)      { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  366.     static void jt_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  367.     static void jnz(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  368.     static void jz(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
  369.     static void jtf(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); R.t_flag = 0; } }
  370. #else
  371.     static void jmp_1(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x100 | R.A11;  }
  372.     static void jmp_2(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x200 | R.A11;  }
  373.     static void jmp_3(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x300 | R.A11;  }
  374.     static void jmp_4(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x400 | R.A11;  }
  375.     static void jmp_5(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x500 | R.A11;  }
  376.     static void jmp_6(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x600 | R.A11;  }
  377.     static void jmp_7(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x700 | R.A11;  }
  378.     static void jmpp_xa(void)     { UINT16 addr = (R.PC.w.l & 0xf00) | R.A; R.PC.w.l = (R.PC.w.l & 0xf00) | M_RDMEM(addr);  }
  379.     static void jb_0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  380.     static void jb_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  381.     static void jb_2(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  382.     static void jb_3(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  383.     static void jb_4(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  384.     static void jb_5(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  385.     static void jb_6(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  386.     static void jb_7(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  387.     static void jf0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
  388.     static void jf_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
  389.     static void jnc(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
  390.     static void jc(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)    { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
  391.     static void jni(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state != CLEAR_LINE) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
  392.     static void jnt_0(void)      { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  393.     static void jt_0(void)         { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  394.     static void jnt_1(void)      { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  395.     static void jt_1(void)         { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  396.     static void jnz(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  397.     static void jz(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
  398.     static void jtf(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)     { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  R.t_flag = 0; } }
  399. #endif
  400.  
  401. static void mov_a_n(void)    { R.A = M_RDMEM_OPCODE(); }
  402. static void mov_a_r0(void)   { R.A = R0; }
  403. static void mov_a_r1(void)   { R.A = R1; }
  404. static void mov_a_r2(void)   { R.A = R2; }
  405. static void mov_a_r3(void)   { R.A = R3; }
  406. static void mov_a_r4(void)   { R.A = R4; }
  407. static void mov_a_r5(void)   { R.A = R5; }
  408. static void mov_a_r6(void)   { R.A = R6; }
  409. static void mov_a_r7(void)   { R.A = R7; }
  410. static void mov_a_psw(void)  { R.A = R.PSW; }
  411. static void mov_a_xr0(void)  { R.A = intRAM[R0 & 0x7f]; }
  412. static void mov_a_xr1(void)  { R.A = intRAM[R1 & 0x7f]; }
  413. static void mov_r0_a(void)   { R0 = R.A; }
  414. static void mov_r1_a(void)   { R1 = R.A; }
  415. static void mov_r2_a(void)   { R2 = R.A; }
  416. static void mov_r3_a(void)   { R3 = R.A; }
  417. static void mov_r4_a(void)   { R4 = R.A; }
  418. static void mov_r5_a(void)   { R5 = R.A; }
  419. static void mov_r6_a(void)   { R6 = R.A; }
  420. static void mov_r7_a(void)   { R7 = R.A; }
  421. static void mov_psw_a(void)  { R.PSW = R.A; regPTR = ((M_By) ? 24 : 0); R.SP = (R.PSW & 7) << 1; }
  422. static void mov_r0_n(void)   { R0 = M_RDMEM_OPCODE(); }
  423. static void mov_r1_n(void)   { R1 = M_RDMEM_OPCODE(); }
  424. static void mov_r2_n(void)   { R2 = M_RDMEM_OPCODE(); }
  425. static void mov_r3_n(void)   { R3 = M_RDMEM_OPCODE(); }
  426. static void mov_r4_n(void)   { R4 = M_RDMEM_OPCODE(); }
  427. static void mov_r5_n(void)   { R5 = M_RDMEM_OPCODE(); }
  428. static void mov_r6_n(void)   { R6 = M_RDMEM_OPCODE(); }
  429. static void mov_r7_n(void)   { R7 = M_RDMEM_OPCODE(); }
  430. static void mov_a_t(void)    { R.A = R.timer; }
  431. static void mov_t_a(void)    { R.timer = R.A; }
  432. static void mov_xr0_a(void)  { intRAM[R0 & 0x7f] = R.A; }
  433. static void mov_xr1_a(void)  { intRAM[R1 & 0x7f] = R.A; }
  434. static void mov_xr0_n(void)  { intRAM[R0 & 0x7f] = M_RDMEM_OPCODE(); }
  435. static void mov_xr1_n(void)  { intRAM[R1 & 0x7f] = M_RDMEM_OPCODE(); }
  436. static void movd_a_p4(void)  { R.A = port_r(4); }
  437. static void movd_a_p5(void)  { R.A = port_r(5); }
  438. static void movd_a_p6(void)  { R.A = port_r(6); }
  439. static void movd_a_p7(void)  { R.A = port_r(7); }
  440. static void movd_p4_a(void)  { port_w(4, R.A); }
  441. static void movd_p5_a(void)  { port_w(5, R.A); }
  442. static void movd_p6_a(void)  { port_w(6, R.A); }
  443. static void movd_p7_a(void)  { port_w(7, R.A); }
  444. static void movp_a_xa(void)  { R.A = M_RDMEM((R.PC.w.l & 0x0f00) | R.A); }
  445. static void movp3_a_xa(void) { R.A = M_RDMEM(0x300 | R.A); }
  446. static void movx_a_xr0(void) { R.A = M_IN(R0); }
  447. static void movx_a_xr1(void) { R.A = M_IN(R1); }
  448. static void movx_xr0_a(void) { M_OUT(R0, R.A); }
  449. static void movx_xr1_a(void) { M_OUT(R1, R.A); }
  450. static void nop(void) { }
  451. static void orl_a_n(void)    { R.A |= M_RDMEM_OPCODE(); }
  452. static void orl_a_r0(void)   { R.A |= R0; }
  453. static void orl_a_r1(void)   { R.A |= R1; }
  454. static void orl_a_r2(void)   { R.A |= R2; }
  455. static void orl_a_r3(void)   { R.A |= R3; }
  456. static void orl_a_r4(void)   { R.A |= R4; }
  457. static void orl_a_r5(void)   { R.A |= R5; }
  458. static void orl_a_r6(void)   { R.A |= R6; }
  459. static void orl_a_r7(void)   { R.A |= R7; }
  460. static void orl_a_xr0(void)  { R.A |= intRAM[R0 & 0x7f]; }
  461. static void orl_a_xr1(void)  { R.A |= intRAM[R1 & 0x7f]; }
  462. static void orl_bus_n(void)  { bus_w( bus_r() | M_RDMEM_OPCODE() ); }
  463. static void orl_p1_n(void)   { port_w(1, port_r(1) | M_RDMEM_OPCODE() ); }
  464. static void orl_p2_n(void)   { port_w(2, port_r(2) | M_RDMEM_OPCODE() ); }
  465. static void orld_p4_a(void)  { port_w(4, port_r(4) | R.A ); }
  466. static void orld_p5_a(void)  { port_w(5, port_r(5) | R.A ); }
  467. static void orld_p6_a(void)  { port_w(6, port_r(6) | R.A ); }
  468. static void orld_p7_a(void)  { port_w(7, port_r(7) | R.A ); }
  469. static void outl_bus_a(void) { bus_w(R.A); }
  470. static void outl_p1_a(void)  { port_w(1, R.A ); }
  471. static void outl_p2_a(void)  { port_w(2, R.A ); }
  472. #ifdef MESS
  473.     static void ret(void)         { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull(); change_pc(R.PC.w.l); }
  474. #else
  475.     static void ret(void)         { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull();  }
  476. #endif
  477.  
  478. static void retr(void)
  479. {
  480.     UINT8 i=pull();
  481.     R.PC.w.l = ((i & 0x0f) << 8) | pull();
  482.     #ifdef MESS
  483.         change_pc(R.PC.w.l);
  484.     #endif
  485.     R.irq_executing = I8039_IGNORE_INT;
  486. //    R.A11 = R.A11ff;    /* NS990113 */
  487.     R.PSW = (R.PSW & 0x0f) | (i & 0xf0);   /* Stack is already changed by pull */
  488.     regPTR = ((M_By) ? 24 : 0);
  489. }
  490. static void rl_a(void)         { UINT8 i=R.A & 0x80; R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
  491. /* NS990113 */
  492. static void rlc_a(void)      { UINT8 i=M_Cy; if (R.A & 0x80) SET(C_FLAG); else CLR(C_FLAG); R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
  493. static void rr_a(void)         { UINT8 i=R.A & 1; R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
  494. /* NS990113 */
  495. static void rrc_a(void)      { UINT8 i=M_Cy; if (R.A & 1) SET(C_FLAG); else CLR(C_FLAG); R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
  496. static void sel_mb0(void)    { R.A11 = 0; R.A11ff = 0; }
  497. static void sel_mb1(void)    { R.A11ff = 0x800; if (R.irq_executing == I8039_IGNORE_INT) R.A11 = 0x800; }
  498. static void sel_rb0(void)    { CLR(B_FLAG); regPTR = 0;  }
  499. static void sel_rb1(void)    { SET(B_FLAG); regPTR = 24; }
  500. static void stop_tcnt(void)  { R.timerON = R.countON = 0; }
  501. static void strt_cnt(void)   { R.countON = 1; Old_T1 = test_r(1); }    /* NS990113 */
  502. static void strt_t(void)     { R.timerON = 1; R.masterClock = 0; }    /* NS990113 */
  503. static void swap_a(void)     { UINT8 i=R.A >> 4; R.A <<= 4; R.A |= i; }
  504. static void xch_a_r0(void)     { UINT8 i=R.A; R.A=R0; R0=i; }
  505. static void xch_a_r1(void)     { UINT8 i=R.A; R.A=R1; R1=i; }
  506. static void xch_a_r2(void)     { UINT8 i=R.A; R.A=R2; R2=i; }
  507. static void xch_a_r3(void)     { UINT8 i=R.A; R.A=R3; R3=i; }
  508. static void xch_a_r4(void)     { UINT8 i=R.A; R.A=R4; R4=i; }
  509. static void xch_a_r5(void)     { UINT8 i=R.A; R.A=R5; R5=i; }
  510. static void xch_a_r6(void)     { UINT8 i=R.A; R.A=R6; R6=i; }
  511. static void xch_a_r7(void)     { UINT8 i=R.A; R.A=R7; R7=i; }
  512. static void xch_a_xr0(void)  { UINT8 i=R.A; R.A=intRAM[R0 & 0x7f]; intRAM[R0 & 0x7f]=i; }
  513. static void xch_a_xr1(void)  { UINT8 i=R.A; R.A=intRAM[R1 & 0x7f]; intRAM[R1 & 0x7f]=i; }
  514. static void xchd_a_xr0(void) { M_XCHD(R0 & 0x7f); }
  515. static void xchd_a_xr1(void) { M_XCHD(R1 & 0x7f); }
  516. static void xrl_a_n(void)    { R.A ^= M_RDMEM_OPCODE(); }
  517. static void xrl_a_r0(void)   { R.A ^= R0; }
  518. static void xrl_a_r1(void)   { R.A ^= R1; }
  519. static void xrl_a_r2(void)   { R.A ^= R2; }
  520. static void xrl_a_r3(void)   { R.A ^= R3; }
  521. static void xrl_a_r4(void)   { R.A ^= R4; }
  522. static void xrl_a_r5(void)   { R.A ^= R5; }
  523. static void xrl_a_r6(void)   { R.A ^= R6; }
  524. static void xrl_a_r7(void)   { R.A ^= R7; }
  525. static void xrl_a_xr0(void)  { R.A ^= intRAM[R0 & 0x7f]; }
  526. static void xrl_a_xr1(void)  { R.A ^= intRAM[R1 & 0x7f]; }
  527.  
  528. static s_opcode opcode_main[256]=
  529. {
  530.     {1, nop        },{0, illegal    },{2, outl_bus_a },{2, add_a_n      },{2, jmp        },{1, en_i        },{0, illegal     },{1, dec_a      },
  531.     {2, ins_a_bus  },{2, in_a_p1    },{2, in_a_p2     },{0, illegal      },{2, movd_a_p4  },{2, movd_a_p5    },{2, movd_a_p6  },{2, movd_a_p7  },
  532.     {1, inc_xr0    },{1, inc_xr1    },{2, jb_0         },{2, adc_a_n      },{2, call       },{1, dis_i        },{2, jtf         },{1, inc_a      },
  533.     {1, inc_r0       },{1, inc_r1     },{1, inc_r2     },{1, inc_r3      },{1, inc_r4       },{1, inc_r5     },{1, inc_r6     },{1, inc_r7      },
  534.     {1, xch_a_xr0  },{1, xch_a_xr1    },{0, illegal     },{2, mov_a_n      },{2, jmp_1       },{1, en_tcnti    },{2, jnt_0      },{1, clr_a      },
  535.     {1, xch_a_r0   },{1, xch_a_r1    },{1, xch_a_r2     },{1, xch_a_r3   },{1, xch_a_r4   },{1, xch_a_r5    },{1, xch_a_r6     },{1, xch_a_r7   },
  536.     {1, xchd_a_xr0 },{1, xchd_a_xr1 },{2, jb_1         },{0, illegal      },{2, call_1       },{1, dis_tcnti    },{2, jt_0         },{1, cpl_a      },
  537.     {0, illegal    },{2, outl_p1_a    },{2, outl_p2_a  },{0, illegal      },{2, movd_p4_a  },{2, movd_p5_a    },{2, movd_p6_a  },{2, movd_p7_a  },
  538.     {1, orl_a_xr0  },{1, orl_a_xr1    },{1, mov_a_t     },{2, orl_a_n      },{2, jmp_2       },{1, strt_cnt    },{2, jnt_1      },{1, swap_a      },
  539.     {1, orl_a_r0   },{1, orl_a_r1    },{1, orl_a_r2     },{1, orl_a_r3   },{1, orl_a_r4   },{1, orl_a_r5    },{1, orl_a_r6     },{1, orl_a_r7   },
  540.     {1, anl_a_xr0  },{1, anl_a_xr1    },{2, jb_2         },{2, anl_a_n      },{2, call_2       },{1, strt_t     },{2, jt_1         },{1, daa_a      },
  541.     {1, anl_a_r0   },{1, anl_a_r1    },{1, anl_a_r2     },{1, anl_a_r3   },{1, anl_a_r4   },{1, anl_a_r5    },{1, anl_a_r6     },{1, anl_a_r7   },
  542.     {1, add_a_xr0  },{1, add_a_xr1    },{1, mov_t_a     },{0, illegal      },{2, jmp_3       },{1, stop_tcnt    },{0, illegal     },{1, rrc_a      },
  543.     {1, add_a_r0   },{1, add_a_r1    },{1, add_a_r2     },{1, add_a_r3   },{1, add_a_r4   },{1, add_a_r5    },{1, add_a_r6     },{1, add_a_r7   },
  544.     {1, adc_a_xr0  },{1, adc_a_xr1    },{2, jb_3         },{0, illegal      },{2, call_3       },{1, ento_clk    },{2, jf_1         },{1, rr_a       },
  545.     {1, adc_a_r0   },{1, adc_a_r1    },{1, adc_a_r2     },{1, adc_a_r3   },{1, adc_a_r4   },{1, adc_a_r5    },{1, adc_a_r6     },{1, adc_a_r7   },
  546.     {2, movx_a_xr0 },{2, movx_a_xr1 },{0, illegal     },{2, ret          },{2, jmp_4       },{1, clr_f0     },{2, jni         },{0, illegal      },
  547.     {2, orl_bus_n  },{2, orl_p1_n    },{2, orl_p2_n     },{0, illegal      },{2, orld_p4_a  },{2, orld_p5_a    },{2, orld_p6_a  },{2, orld_p7_a  },
  548.     {2, movx_xr0_a },{2, movx_xr1_a },{2, jb_4         },{2, retr       },{2, call_4       },{1, cpl_f0     },{2, jnz         },{1, clr_c      },
  549.     {2, anl_bus_n  },{2, anl_p1_n    },{2, anl_p2_n     },{0, illegal      },{2, anld_p4_a  },{2, anld_p5_a    },{2, anld_p6_a  },{2, anld_p7_a  },
  550.     {1, mov_xr0_a  },{1, mov_xr1_a    },{0, illegal     },{2, movp_a_xa  },{2, jmp_5       },{1, clr_f1     },{0, illegal     },{1, cpl_c      },
  551.     {1, mov_r0_a   },{1, mov_r1_a    },{1, mov_r2_a     },{1, mov_r3_a   },{1, mov_r4_a   },{1, mov_r5_a    },{1, mov_r6_a     },{1, mov_r7_a   },
  552.     {2, mov_xr0_n  },{2, mov_xr1_n    },{2, jb_5         },{2, jmpp_xa      },{2, call_5       },{1, cpl_f1     },{2, jf0         },{0, illegal      },
  553.     {2, mov_r0_n   },{2, mov_r1_n    },{2, mov_r2_n     },{2, mov_r3_n   },{2, mov_r4_n   },{2, mov_r5_n    },{2, mov_r6_n     },{2, mov_r7_n   },
  554.     {0, illegal    },{0, illegal    },{0, illegal     },{0, illegal      },{2, jmp_6       },{1, sel_rb0    },{2, jz         },{1, mov_a_psw  },
  555.     {1, dec_r0       },{1, dec_r1     },{1, dec_r2     },{1, dec_r3      },{1, dec_r4       },{1, dec_r5     },{1, dec_r6     },{1, dec_r7      },
  556.     {1, xrl_a_xr0  },{1, xrl_a_xr1    },{2, jb_6         },{2, xrl_a_n      },{2, call_6       },{1, sel_rb1    },{0, illegal     },{1, mov_psw_a  },
  557.     {1, xrl_a_r0   },{1, xrl_a_r1    },{1, xrl_a_r2     },{1, xrl_a_r3   },{1, xrl_a_r4   },{1, xrl_a_r5    },{1, xrl_a_r6     },{1, xrl_a_r7   },
  558.     {0, illegal    },{0, illegal    },{0, illegal     },{2, movp3_a_xa },{2, jmp_7       },{1, sel_mb0    },{2, jnc         },{1, rl_a       },
  559.     {2, djnz_r0    },{2, djnz_r1    },{2, djnz_r2     },{2, djnz_r3      },{2, djnz_r4    },{2, djnz_r5    },{2, djnz_r6     },{2, djnz_r7      },
  560.     {1, mov_a_xr0  },{1, mov_a_xr1    },{2, jb_7         },{0, illegal      },{2, call_7       },{1, sel_mb1    },{2, jc         },{1, rlc_a      },
  561.     {1, mov_a_r0   },{1, mov_a_r1    },{1, mov_a_r2     },{1, mov_a_r3   },{1, mov_a_r4   },{1, mov_a_r5    },{1, mov_a_r6     },{1, mov_a_r7   }
  562. };
  563.  
  564.  
  565. /****************************************************************************
  566.  * Issue an interrupt if necessary
  567.  ****************************************************************************/
  568. static int Timer_IRQ(void)
  569. {
  570.     if (R.tirq_en && !R.irq_executing)
  571.     {
  572.         logerror("I8039:  TIMER INTERRUPT\n");
  573.         R.irq_executing = I8039_TIMER_INT;
  574.         push(R.PC.b.l);
  575.         push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
  576.         R.PC.w.l = 0x07;
  577.         #ifdef MESS
  578.             change_pc(0x07);
  579.         #endif
  580.         R.A11ff = R.A11;
  581.         R.A11    = 0;
  582.         return 2;        /* 2 clock cycles used */
  583.     }
  584.     return 0;
  585. }
  586.  
  587. static int Ext_IRQ(void)
  588. {
  589.     if (R.xirq_en) {
  590. //logerror("I8039:  EXT INTERRUPT\n");
  591.         R.irq_executing = I8039_EXT_INT;
  592.         push(R.PC.b.l);
  593.         push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
  594.         R.PC.w.l = 0x03;
  595.         R.A11ff = R.A11;
  596.         R.A11   = 0;
  597.         return 2;       /* 2 clock cycles used */
  598.     }
  599.     return 0;
  600. }
  601.  
  602.  
  603.  
  604. /****************************************************************************
  605.  * Reset registers to their initial values
  606.  ****************************************************************************/
  607. void i8039_reset (void *param)
  608. {
  609.     R.PC.w.l  = 0;
  610.     R.SP  = 0;
  611.     R.A   = 0;
  612.     R.PSW = 0x08;        /* Start with Carry SET, Bit 4 is always SET */
  613.     memset(R.RAM, 0x0, 128);
  614.     R.bus = 0;
  615.     R.irq_executing = I8039_IGNORE_INT;
  616.     R.pending_irq    = I8039_IGNORE_INT;
  617.  
  618.     R.A11ff   = R.A11     = 0;
  619.     R.timerON = R.countON = 0;
  620.     R.tirq_en = R.xirq_en = 0;
  621.     R.xirq_en = 0;    /* NS990113 */
  622.     R.timerON = 1;    /* Mario Bros. doesn't work without this */
  623.     R.masterClock = 0;
  624. }
  625.  
  626.  
  627. /****************************************************************************
  628.  * Shut down CPU emulation
  629.  ****************************************************************************/
  630. void i8039_exit (void)
  631. {
  632.     /* nothing to do ? */
  633. }
  634.  
  635. /****************************************************************************
  636.  * Execute cycles CPU cycles. Return number of cycles really executed
  637.  ****************************************************************************/
  638. int i8039_execute(int cycles)
  639. {
  640.     unsigned opcode, T1;
  641.     int count;
  642.  
  643.     i8039_ICount=cycles;
  644.  
  645.     do {
  646.         switch (R.pending_irq)
  647.         {
  648.             case I8039_COUNT_INT:
  649.             case I8039_TIMER_INT:
  650.                 count = Timer_IRQ();
  651.                 i8039_ICount -= count;
  652.                 if (R.timerON)  /* NS990113 */
  653.                     R.masterClock += count;
  654.                 R.t_flag = 1;
  655.                 break;
  656.             case I8039_EXT_INT:
  657.                 if (R.irq_callback) (*R.irq_callback)(0);
  658.                 count = Ext_IRQ();
  659.                 i8039_ICount -= count;
  660.                 if (R.timerON)  /* NS990113 */
  661.                     R.masterClock += count;
  662.                 break;
  663.         }
  664.         R.pending_irq = I8039_IGNORE_INT;
  665.  
  666.         R.PREPC = R.PC;
  667.  
  668.         CALL_MAME_DEBUG;
  669.  
  670.         opcode=M_RDOP(R.PC.w.l);
  671.  
  672. /*      logerror("I8039:  PC = %04x,  opcode = %02x\n", R.PC.w.l, opcode); */
  673.  
  674.         R.PC.w.l++;
  675.         i8039_ICount -= opcode_main[opcode].cycles;
  676.         (*(opcode_main[opcode].function))();
  677.  
  678.         if (R.countON)  /* NS990113 */
  679.         {
  680.             T1 = test_r(1);
  681.             if (POSITIVE_EDGE_T1)
  682.             {   /* Handle COUNTER IRQs */
  683.                 R.timer++;
  684.                 if (R.timer == 0) R.pending_irq = I8039_COUNT_INT;
  685.  
  686.                 Old_T1 = T1;
  687.             }
  688.         }
  689.  
  690.         if (R.timerON) {                        /* Handle TIMER IRQs */
  691.             R.masterClock += opcode_main[opcode].cycles;
  692.             if (R.masterClock >= 32) {  /* NS990113 */
  693.                 R.masterClock -= 32;
  694.                 R.timer++;
  695.                 if (R.timer == 0) R.pending_irq = I8039_TIMER_INT;
  696.             }
  697.         }
  698.    } while (i8039_ICount>0);
  699.  
  700.    return cycles - i8039_ICount;
  701. }
  702.  
  703. /****************************************************************************
  704.  * Get all registers in given buffer
  705.  ****************************************************************************/
  706. unsigned i8039_get_context (void *dst)
  707. {
  708.     if( dst )
  709.         *(I8039_Regs*)dst = R;
  710.     return sizeof(I8039_Regs);
  711. }
  712.  
  713.  
  714. /****************************************************************************
  715.  * Set all registers to given values
  716.  ****************************************************************************/
  717. void i8039_set_context (void *src)
  718. {
  719.     if( src )
  720.     {
  721.         R = *(I8039_Regs*)src;
  722.         regPTR = ((M_By) ? 24 : 0);
  723.         R.SP = (R.PSW << 1) & 0x0f;
  724.         #ifdef MESS
  725.             change_pc(R.PC.w.l);
  726.         #endif
  727.     }
  728. }
  729.  
  730.  
  731. /****************************************************************************
  732.  * Return program counter
  733.  ****************************************************************************/
  734. unsigned i8039_get_pc (void)
  735. {
  736.     return R.PC.d;
  737. }
  738.  
  739.  
  740. /****************************************************************************
  741.  * Return program counter
  742.  ****************************************************************************/
  743. void i8039_set_pc (unsigned val)
  744. {
  745.     R.PC.w.l = val;
  746. }
  747.  
  748.  
  749. /****************************************************************************
  750.  * Return stack pointer
  751.  ****************************************************************************/
  752. unsigned i8039_get_sp (void)
  753. {
  754.     return R.SP;
  755. }
  756.  
  757.  
  758. /****************************************************************************
  759.  * Set stack pointer
  760.  ****************************************************************************/
  761. void i8039_set_sp (unsigned val)
  762. {
  763.     R.SP = val;
  764. }
  765.  
  766.  
  767. /****************************************************************************/
  768. /* Get a specific register                                                  */
  769. /****************************************************************************/
  770. unsigned i8039_get_reg (int regnum)
  771. {
  772.     switch( regnum )
  773.     {
  774.         case I8039_PC: return R.PC.w.l;
  775.         case I8039_SP: return R.SP;
  776.         case I8039_PSW: return R.PSW;
  777.         case I8039_A: return R.A;
  778.         case I8039_IRQ_STATE: return R.irq_state;
  779.         case I8039_R0: return R0;
  780.         case I8039_R1: return R1;
  781.         case I8039_R2: return R2;
  782.         case I8039_R3: return R3;
  783.         case I8039_R4: return R4;
  784.         case I8039_R5: return R5;
  785.         case I8039_R6: return R6;
  786.         case I8039_R7: return R7;
  787.         case REG_PREVIOUSPC: return R.PREPC.w.l;
  788.         default:
  789.             if( regnum <= REG_SP_CONTENTS )
  790.             {
  791.                 unsigned offset = 8 + 2 * ((R.SP + REG_SP_CONTENTS - regnum) & 7);
  792.                 return R.RAM[offset] + 256 * R.RAM[offset+1];
  793.             }
  794.     }
  795.     return 0;
  796. }
  797.  
  798.  
  799. /****************************************************************************/
  800. /* Set a specific register                                                  */
  801. /****************************************************************************/
  802. void i8039_set_reg (int regnum, unsigned val)
  803. {
  804.     switch( regnum )
  805.     {
  806.         case I8039_PC: R.PC.w.l = val; break;
  807.         case I8039_SP: R.SP = val; break;
  808.         case I8039_PSW: R.PSW = val; break;
  809.         case I8039_A: R.A = val; break;
  810.         case I8039_IRQ_STATE: i8039_set_irq_line( 0, val ); break;
  811.         case I8039_R0: R0 = val; break;
  812.         case I8039_R1: R1 = val; break;
  813.         case I8039_R2: R2 = val; break;
  814.         case I8039_R3: R3 = val; break;
  815.         case I8039_R4: R4 = val; break;
  816.         case I8039_R5: R5 = val; break;
  817.         case I8039_R6: R6 = val; break;
  818.         case I8039_R7: R7 = val; break;
  819.         default:
  820.             if( regnum <= REG_SP_CONTENTS )
  821.             {
  822.                 unsigned offset = 8 + 2 * ((R.SP + REG_SP_CONTENTS - regnum) & 7);
  823.                 R.RAM[offset] = val & 0xff;
  824.                 R.RAM[offset+1] = val >> 8;
  825.             }
  826.     }
  827. }
  828.  
  829.  
  830. /****************************************************************************/
  831. /* Set NMI line state                                                        */
  832. /****************************************************************************/
  833. void i8039_set_nmi_line(int state)
  834. {
  835.     /* I8039 does not have a NMI line */
  836. }
  837.  
  838. /****************************************************************************/
  839. /* Set IRQ line state                                                        */
  840. /****************************************************************************/
  841. void i8039_set_irq_line(int irqline, int state)
  842. {
  843.     R.irq_state = state;
  844.     if (state == CLEAR_LINE)
  845.         R.pending_irq &= ~I8039_EXT_INT;
  846.     else
  847.         R.pending_irq |= I8039_EXT_INT;
  848. }
  849.  
  850. /****************************************************************************/
  851. /* Set IRQ callback (interrupt acknowledge)                                 */
  852. /****************************************************************************/
  853. void i8039_set_irq_callback(int (*callback)(int irqline))
  854. {
  855.     R.irq_callback = callback;
  856. }
  857.  
  858. /****************************************************************************
  859.  * Return a formatted string for a register
  860.  ****************************************************************************/
  861. const char *i8039_info(void *context, int regnum)
  862. {
  863.     static char buffer[8][47+1];
  864.     static int which = 0;
  865.     I8039_Regs *r = context;
  866.  
  867.     which = ++which % 8;
  868.     buffer[which][0] = '\0';
  869.     if( !context )
  870.         r = &R;
  871.  
  872.     switch( regnum )
  873.     {
  874.         case CPU_INFO_REG+I8039_PC: sprintf(buffer[which], "PC:%04X", r->PC.w.l); break;
  875.         case CPU_INFO_REG+I8039_SP: sprintf(buffer[which], "SP:%02X", r->SP); break;
  876.         case CPU_INFO_REG+I8039_PSW: sprintf(buffer[which], "PSW:%02X", r->PSW); break;
  877.         case CPU_INFO_REG+I8039_A: sprintf(buffer[which], "A:%02X", r->A); break;
  878.         case CPU_INFO_REG+I8039_IRQ_STATE: sprintf(buffer[which], "IRQ:%X", r->irq_state); break;
  879.         case CPU_INFO_REG+I8039_R0: sprintf(buffer[which], "R0:%02X", r->RAM[r->regPtr+0]); break;
  880.         case CPU_INFO_REG+I8039_R1: sprintf(buffer[which], "R1:%02X", r->RAM[r->regPtr+1]); break;
  881.         case CPU_INFO_REG+I8039_R2: sprintf(buffer[which], "R2:%02X", r->RAM[r->regPtr+2]); break;
  882.         case CPU_INFO_REG+I8039_R3: sprintf(buffer[which], "R3:%02X", r->RAM[r->regPtr+3]); break;
  883.         case CPU_INFO_REG+I8039_R4: sprintf(buffer[which], "R4:%02X", r->RAM[r->regPtr+4]); break;
  884.         case CPU_INFO_REG+I8039_R5: sprintf(buffer[which], "R5:%02X", r->RAM[r->regPtr+5]); break;
  885.         case CPU_INFO_REG+I8039_R6: sprintf(buffer[which], "R6:%02X", r->RAM[r->regPtr+6]); break;
  886.         case CPU_INFO_REG+I8039_R7: sprintf(buffer[which], "R7:%02X", r->RAM[r->regPtr+7]); break;
  887.         case CPU_INFO_FLAGS:
  888.             sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
  889.                 r->PSW & 0x80 ? 'C':'.',
  890.                 r->PSW & 0x40 ? 'A':'.',
  891.                 r->PSW & 0x20 ? 'F':'.',
  892.                 r->PSW & 0x10 ? 'B':'.',
  893.                 r->PSW & 0x08 ? '?':'.',
  894.                 r->PSW & 0x04 ? '4':'.',
  895.                 r->PSW & 0x02 ? '2':'.',
  896.                 r->PSW & 0x01 ? '1':'.');
  897.             break;
  898.         case CPU_INFO_NAME: return "I8039";
  899.         case CPU_INFO_FAMILY: return "Intel 8039";
  900.         case CPU_INFO_VERSION: return "1.1";
  901.         case CPU_INFO_FILE: return __FILE__;
  902.         case CPU_INFO_CREDITS: return "Copyright (C) 1997 by Mirko Buffoni\nBased on the original work (C) 1997 by Dan Boris";
  903.         case CPU_INFO_REG_LAYOUT: return (const char*)i8039_reg_layout;
  904.         case CPU_INFO_WIN_LAYOUT: return (const char*)i8039_win_layout;
  905.     }
  906.     return buffer[which];
  907. }
  908.  
  909. unsigned i8039_dasm(char *buffer, unsigned pc)
  910. {
  911. #ifdef    MAME_DEBUG
  912.     return Dasm8039(buffer,pc);
  913. #else
  914.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  915.     return 1;
  916. #endif
  917. }
  918.  
  919. /**************************************************************************
  920.  * I8035 section
  921.  **************************************************************************/
  922. #if (HAS_I8035)
  923. /* Layout of the registers in the debugger */
  924. static UINT8 i8035_reg_layout[] = {
  925.     I8035_PC, I8035_SP, I8035_PSW, I8035_A, I8035_IRQ_STATE, -1,
  926.     I8035_R0, I8035_R1, I8035_R2, I8035_R3, I8035_R4, I8035_R5, I8035_R6, I8035_R7, 0
  927. };
  928.  
  929. /* Layout of the debugger windows x,y,w,h */
  930. static UINT8 i8035_win_layout[] = {
  931.      0, 0,80, 2,    /* register window (top rows) */
  932.      0, 3,24,19,    /* disassembler window (left colums) */
  933.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  934.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  935.      0,23,80, 1,    /* command line window (bottom rows) */
  936. };
  937.  
  938. void i8035_reset(void *param) { i8039_reset(param); }
  939. void i8035_exit(void) { i8039_exit(); }
  940. int i8035_execute(int cycles) { return i8039_execute(cycles); }
  941. unsigned i8035_get_context(void *dst) { return i8039_get_context(dst); }
  942. void i8035_set_context(void *src)  { i8039_set_context(src); }
  943. unsigned i8035_get_pc(void) { return i8039_get_pc(); }
  944. void i8035_set_pc(unsigned val) { i8039_set_pc(val); }
  945. unsigned i8035_get_sp(void) { return i8039_get_sp(); }
  946. void i8035_set_sp(unsigned val) { i8039_set_sp(val); }
  947. unsigned i8035_get_reg(int regnum) { return i8039_get_reg(regnum); }
  948. void i8035_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
  949. void i8035_set_nmi_line(int state) { i8039_set_nmi_line(state); }
  950. void i8035_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
  951. void i8035_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
  952. const char *i8035_info(void *context, int regnum)
  953. {
  954.     switch( regnum )
  955.     {
  956.         case CPU_INFO_NAME: return "I8035";
  957.         case CPU_INFO_VERSION: return "1.1";
  958.         case CPU_INFO_REG_LAYOUT: return (const char*)i8035_reg_layout;
  959.         case CPU_INFO_WIN_LAYOUT: return (const char*)i8035_win_layout;
  960.     }
  961.     return i8039_info(context,regnum);
  962. }
  963.  
  964. unsigned i8035_dasm(char *buffer, unsigned pc)
  965. {
  966. #ifdef MAME_DEBUG
  967.     return Dasm8039(buffer,pc);
  968. #else
  969.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  970.     return 1;
  971. #endif
  972. }
  973.  
  974. #endif
  975.  
  976. /**************************************************************************
  977.  * I8048 section
  978.  **************************************************************************/
  979. #if (HAS_I8048)
  980. /* Layout of the registers in the debugger */
  981. static UINT8 i8048_reg_layout[] = {
  982.     I8048_PC, I8048_SP, I8048_PSW, I8048_A, I8048_IRQ_STATE, -1,
  983.     I8048_R0, I8048_R1, I8048_R2, I8048_R3, I8048_R4, I8048_R5, I8048_R6, I8048_R7, 0
  984. };
  985.  
  986. /* Layout of the debugger windows x,y,w,h */
  987. static UINT8 i8048_win_layout[] = {
  988.      0, 0,80, 2,    /* register window (top rows) */
  989.      0, 3,24,19,    /* disassembler window (left colums) */
  990.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  991.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  992.      0,23,80, 1,    /* command line window (bottom rows) */
  993. };
  994.  
  995. void i8048_reset(void *param) { i8039_reset(param); }
  996. void i8048_exit(void) { i8039_exit(); }
  997. int i8048_execute(int cycles) { return i8039_execute(cycles); }
  998. unsigned i8048_get_context(void *dst) { return i8039_get_context(dst); }
  999. void i8048_set_context(void *src)  { i8039_set_context(src); }
  1000. unsigned i8048_get_pc(void) { return i8039_get_pc(); }
  1001. void i8048_set_pc(unsigned val) { i8039_set_pc(val); }
  1002. unsigned i8048_get_sp(void) { return i8039_get_sp(); }
  1003. void i8048_set_sp(unsigned val) { i8039_set_sp(val); }
  1004. unsigned i8048_get_reg(int regnum) { return i8039_get_reg(regnum); }
  1005. void i8048_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
  1006. void i8048_set_nmi_line(int state) { i8039_set_nmi_line(state); }
  1007. void i8048_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
  1008. void i8048_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
  1009. const char *i8048_info(void *context, int regnum)
  1010. {
  1011.     switch( regnum )
  1012.     {
  1013.         case CPU_INFO_NAME: return "I8048";
  1014.         case CPU_INFO_VERSION: return "1.1";
  1015.         case CPU_INFO_REG_LAYOUT: return (const char*)i8048_reg_layout;
  1016.         case CPU_INFO_WIN_LAYOUT: return (const char*)i8048_win_layout;
  1017.     }
  1018.     return i8039_info(context,regnum);
  1019. }
  1020.  
  1021. unsigned i8048_dasm(char *buffer, unsigned pc)
  1022. {
  1023. #ifdef MAME_DEBUG
  1024.     return Dasm8039(buffer,pc);
  1025. #else
  1026.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  1027.     return 1;
  1028. #endif
  1029. }
  1030. #endif
  1031. /**************************************************************************
  1032.  * N7751 section
  1033.  **************************************************************************/
  1034. #if (HAS_N7751)
  1035. /* Layout of the registers in the debugger */
  1036. static UINT8 n7751_reg_layout[] = {
  1037.     N7751_PC, N7751_SP, N7751_PSW, N7751_A, N7751_IRQ_STATE, -1,
  1038.     N7751_R0, N7751_R1, N7751_R2, N7751_R3, N7751_R4, N7751_R5, N7751_R6, N7751_R7, 0
  1039. };
  1040.  
  1041. /* Layout of the debugger windows x,y,w,h */
  1042. static UINT8 n7751_win_layout[] = {
  1043.      0, 0,80, 2,    /* register window (top rows) */
  1044.      0, 3,24,19,    /* disassembler window (left colums) */
  1045.     25, 3,55, 9,    /* memory #1 window (right, upper middle) */
  1046.     25,13,55, 9,    /* memory #2 window (right, lower middle) */
  1047.      0,23,80, 1,    /* command line window (bottom rows) */
  1048. };
  1049.  
  1050. void n7751_reset(void *param) { i8039_reset(param); }
  1051. void n7751_exit(void) { i8039_exit(); }
  1052. int n7751_execute(int cycles) { return i8039_execute(cycles); }
  1053. unsigned n7751_get_context(void *dst) { return i8039_get_context(dst); }
  1054. void n7751_set_context(void *src)  { i8039_set_context(src); }
  1055. unsigned n7751_get_pc(void) { return i8039_get_pc(); }
  1056. void n7751_set_pc(unsigned val) { i8039_set_pc(val); }
  1057. unsigned n7751_get_sp(void) { return i8039_get_sp(); }
  1058. void n7751_set_sp(unsigned val) { i8039_set_sp(val); }
  1059. unsigned n7751_get_reg(int regnum) { return i8039_get_reg(regnum); }
  1060. void n7751_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
  1061. void n7751_set_nmi_line(int state) { i8039_set_nmi_line(state); }
  1062. void n7751_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
  1063. void n7751_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
  1064. const char *n7751_info(void *context, int regnum)
  1065. {
  1066.     switch( regnum )
  1067.     {
  1068.         case CPU_INFO_NAME: return "N7751";
  1069.         case CPU_INFO_VERSION: return "1.1";
  1070.         case CPU_INFO_REG_LAYOUT: return (const char*)n7751_reg_layout;
  1071.         case CPU_INFO_WIN_LAYOUT: return (const char*)n7751_win_layout;
  1072.     }
  1073.     return i8039_info(context,regnum);
  1074. }
  1075.  
  1076. unsigned n7751_dasm(char *buffer, unsigned pc)
  1077. {
  1078. #ifdef    MAME_DEBUG
  1079.     return Dasm8039(buffer,pc);
  1080. #else
  1081.     sprintf( buffer, "$%02X", cpu_readop(pc) );
  1082.     return 1;
  1083. #endif
  1084. }
  1085. #endif
  1086.  
  1087.